<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas 绘制验证码</title>
</head>
<body>
  <canvas width="150" height="80" id="c1" onclick="fn()">
  <script>
    function fn() {
      // 新建一个函数产生随机数
      function rn(min, max) {
        return parseInt(Math.random() * (max - min) + min);
      }
      // 新建一个函数产生随机颜色
      function rc(min, max) {
        var r = rn(min, max);
        var g = rn(min, max);
        var b = rn(min, max);
        return `rgb(${r},${g},${b})`;
      }
      // 填充背景颜色,颜色要浅一点
      var w = 150;
      var h = 80;
      var ctx = c1.getContext("2d");
      ctx.fillStyle = rc(200, 250);
      ctx.fillRect(0, 0, w, h);
      // 随机产生字符串
      var pool = "ABCDEFGHIJKLIMNOPQRSTUVWSYZ1234567890";
      for (var i = 0; i < 4; i++) {
        var c = pool[rn(0, pool.length)]; // 随机的字
        var fs = rn(18, 40); // 字体的大小
        var deg = rn(-30, 30); // 字体的旋转角度
        ctx.font = fs + 'px Simhei';
        ctx.textBaseline = "top";
        ctx.fillStyle = rc(80, 150);
        ctx.save();
        ctx.translate(30 * i + 15, 15);
        ctx.rotate(deg * Math.PI / 180);
        ctx.fillText(c, -15 + 5, -15);
        ctx.restore();
      }
      // 随机产生5条干扰线,干扰线的颜色要浅一点
      for (var i = 0; i < 5; i++) {
        ctx.beginPath();
        ctx.moveTo(rn(0, w), rn(0, h));
        ctx.lineTo(rn(0, w), rn(0, h));
        ctx.strokeStyle = rc(180, 230);
        ctx.closePath();
        ctx.stroke();
      }
      // 随机产生40个干扰的小点
      for (var i = 0; i < 40; i++) {
        ctx.beginPath();
        ctx.arc(rn(0, w), rn(0, h), 1, 0, 2 * Math.PI);
        ctx.closePath();
        ctx.fillStyle = rc(150, 200);
        ctx.fill();
      }
    }
    fn()
  </script>
</body>
</html>